package cs.ubbcluj.ro.mps.bridge.implementation;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import cs.ubbcluj.ro.datatypes.implementations.SparseMatrix;
import cs.ubbcluj.ro.datatypes.implementations.SparseVector;
import cs.ubbcluj.ro.datatypes.interfaces.Matrix;
import cs.ubbcluj.ro.datatypes.interfaces.Vector;
import cs.ubbcluj.ro.mps.bridge.interfaces.MpsImpInterface;
import cs.ubbcluj.ro.mps.data.MpsImpl;
import cs.ubbcluj.ro.mps.data.interfaces.Constrain;
import cs.ubbcluj.ro.mps.data.interfaces.Mps;

public class SparseMpsImp implements MpsImpInterface{
	 
	Mps theMps;
	 
	public SparseMpsImp(Mps mps){
		theMps=mps;
	}
	
	public SparseMpsImp(){}
	
	public Matrix getCoefficients() {

			final Collection<Constrain> constrainList = theMps.getConstrains().values();

			final int count = theMps.countLGConstrains();

			final Matrix coef = new SparseMatrix(theMps.getConstrains().values().size(),
				theMps.getNumberOfVariables() + count);

			int i = -1;
			int j = -1;
			int k = 0;
			for (final Constrain constrain : constrainList) {
			    j = -1;
			    ++i;
			    for (final Iterator<String> variableNameIterator = theMps.getVariableIndex().iterator(); variableNameIterator.hasNext();) {
				final String variableName = variableNameIterator.next();
				if (constrain.containsVariable(variableName)) {
				    coef.addElement(i, ++j, constrain
					    .getCoefficient(variableName));
				} else {
				    coef.addElement(i, ++j, 0);
				}
			    }
			    switch (constrain.getType()) {
			    case L: {
				coef.addElement(i, theMps.getNumberOfVariables() + k, 1);
				k++;
				break;
			    }
			    case G: {
				coef.addElement(i, theMps.getNumberOfVariables() + k, -1);
				k++;
				break;
			    }
			    default: {

			    }
			    }
			}

			return coef;
		    }

    public Vector getRightHandSideValues() {

    	Map<String, Double> rhsValues = new HashMap<String, Double>();
    	final Iterator<Map<String, Double>> iterator = theMps.getRhs().values()
    		.iterator();
    	if (iterator.hasNext()) {
    	    rhsValues = iterator.next();
    	}

    	final Vector b = new SparseVector(theMps.getConstrains().size());
    	int i = -1;
    	for (final String constrainName : theMps.getConstrains().keySet()) {
    	    if (rhsValues.containsKey(constrainName)) {
    		b.addElement(++i, rhsValues.get(constrainName));
    	    } else {
    		b.addElement(++i, 0f);
    	    }
    	}

    	return b;
        }

    public Vector getTargetCoefficients() {


    	final int count = theMps.countLGConstrains();


    	final Vector c = new SparseVector(this.theMps.getNumberOfVariables() + count);
    	final Map<String, Double> variables = theMps.getTargetFunction().values()
    		.iterator().next().getVariables();

    	int i = -1;
    	for (final Iterator<String> variableNameIterator = theMps.getVariableIndex()
    		.iterator(); variableNameIterator.hasNext();) {
    	    final String variableName = variableNameIterator.next();
    	    if (variables.containsKey(variableName)) {
    		c.addElement(++i, variables.get(variableName));
    	    } else {
    		c.addElement(++i, 0);
    	    }
    	}

    	return c;
        }

    public Vector getLowerBounds() {
    	
    	final Vector lowerBounds = new SparseVector(theMps.getNumberOfVariables());
    	
    	int i = -1;
    	for (final Iterator<String> variableNameIterator = theMps.getVariableIndex()
    			.iterator(); variableNameIterator.hasNext();) {
    		final String variableName = variableNameIterator.next();
    		if (theMps.getLowerBound().containsKey(variableName)) {
    			lowerBounds.addElement(++i, theMps.getLowerBound().get(variableName));
    		} else {
    			lowerBounds.addElement(++i, 0);
    		}
    	}
    	
    	return lowerBounds;
    }
    
    public Vector getUpperBounds() {
    	
    	final Vector upperBounds = new SparseVector(theMps.getNumberOfVariables());
    	
    	int i = -1;
    	for (final Iterator<String> variableNameIterator = theMps.getVariableIndex()
    			.iterator(); variableNameIterator.hasNext();) {
    		final String variableName = variableNameIterator.next();
    		if (theMps.getUpperBound().containsKey(variableName)) {
    			upperBounds.addElement(++i, theMps.getUpperBound().get(variableName));
    		} else { 
    			upperBounds.addElement(++i, 0);
    		}
    	}
    	return upperBounds;
    }
   

	@Override
	public void setTheMps(Mps mps) {
		this.theMps=mps;
	}
}
